package cn.smxy.category.service.impl;

import cn.smxy.category.mapper.PlantFamilyMapper;
import cn.smxy.category.service.PlantFamilyService;
import cn.smxy.client.PlantClient;
import cn.smxy.constant.RegexConstant;
import cn.smxy.dto.FamilyDto;
import cn.smxy.param.FamilyFuzzyParam;
import cn.smxy.param.FamilyIdsParam;
import cn.smxy.pojo.PlantFamily;
import cn.smxy.util.R;
import cn.smxy.vo.FamilyAdminVo;
import cn.smxy.vo.PlantFamilyVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
@Slf4j
public class PlantFamilyServiceImpl implements PlantFamilyService {

    @Autowired
    private PlantFamilyMapper plantFamilyMapper;
    @Autowired
    private PlantClient plantClient;

    /**
     * 展示所有科名
     * 1.父节点等0的为科名
     * @param categoryId
     * @return
     */
    @Override
    public R show(Long categoryId) {
        QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id",categoryId);
        queryWrapper.eq("parent_id",0);
        List<PlantFamily> plantFamilies = plantFamilyMapper.selectList(queryWrapper);
        R ok = R.ok(plantFamilies);
        log.info("PlantFamilyServiceImpl.show业务结束，结果为:{}",ok);
        return ok;
    }

    /**
     * 添加新科名
     * 1.正则校验是否符合规则
     * 2.查询数据库是否存在相同名称
     * 3.添加到数据库
     *
     * @param plantFamily
     * @return
     */
    @Override
    public R addFamily(PlantFamily plantFamily) {
        // 正则校验命名
        Pattern pattern = Pattern.compile(RegexConstant.PLANT_FAMILY);
        Matcher matcher = pattern.matcher(plantFamily.getFamilyName());
        if(!matcher.matches()) {
            log.info("PlantFamilyServiceImpl.addFamily业务结束，结果为:{}","命名不符合规则");
            return R.fail("参数错误，添加失败");
        }
        // 数据库查询是否存在同名
        QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("family_name",plantFamily.getFamilyName());
        Long total = plantFamilyMapper.selectCount(queryWrapper);
        if(total > 0) {
            log.info("PlantFamilyServiceImpl.addFamily业务结束，结果为:{}","存在同名，添加失败");
            return R.fail("存在同名，添加失败");
        }
        // 添加到数据库
        plantFamily.setParentId(0L);
        plantFamilyMapper.insert(plantFamily);
        log.info("PlantFamilyServiceImpl.addFamily业务结束，结果为:{}","添加新科名成功");
        return R.ok("添加新科名成功");
    }

    /**
     * 返回属名列表
     *
     * @param familyId
     * @return
     */
    @Override
    public R genusShow(Long familyId) {
        QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",familyId);
        List<PlantFamily> plantFamilies = plantFamilyMapper.selectList(queryWrapper);
        R ok = R.ok(plantFamilies);
        log.info("PlantFamilyServiceImpl.genusShow业务结束，结果为:{}",ok);
        return ok;
    }

    /**
     * 删除科属
     * 1.判断该科属下是否存在植物作品 如果存在不可删除
     * 2.判断父节点是否为0
     * 2.1 父节点为0则为科，需要删除该科下所有属，仍需判断这些属是否存在植物作品
     * 2.2 父节点不为0直接删除即可
     *
     * @param familyId
     * @return
     */
    @Override
    public R familyRemove(Long familyId) {
        PlantFamily plantFamily = plantFamilyMapper.selectById(familyId);
        if(plantFamily.getParentId() == 0) {
            QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parent_id",familyId);
            plantFamilyMapper.delete(queryWrapper);
        }
        int rows = plantFamilyMapper.deleteById(familyId);
        if(rows == 0) {
            log.info("PlantFamilyServiceImpl.remove业务结束，结果为:{}","删除失败");
            R.fail("删除失败");
        }
        return R.ok("删除成功");
    }

    /**
     * 按条件分页查询科属
     * 1.判断科属是否为空，不为空封装条件
     * 2.判断种群id是否为空，不为空封装条件
     * 3.判断科属id是否为空，不为空封装条件
     * 4.封装分页条件
     * 5.数据库查询
     * 6.结果封装，封装成更适合展示的PlantFamilyVo
     *
     * @param familyFuzzyParam 种群id 科属id 分页参数 模糊查询科属名
     * @return
     */
    @Override
    public R fuzzy(FamilyFuzzyParam familyFuzzyParam) {
        // 条件拆分
        Long familyId = familyFuzzyParam.getFamilyId();
        String familyName = familyFuzzyParam.getFamilyName();
        Long categoryId = familyFuzzyParam.getCategoryId();
        int pageSize = familyFuzzyParam.getPageSize();
        int currentPage = familyFuzzyParam.getCurrentPage();
        // 条件封装
        QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
        if(familyName != null) {
            queryWrapper.like("family_name",familyName);
        }
        if(categoryId != null && categoryId != 0) {
            queryWrapper.eq("category_id",categoryId);
        }
        if(familyId != null && familyId != 0) {
            queryWrapper.eq("parent_id",familyId);
        }
        IPage<PlantFamily> page = new Page<>(currentPage,pageSize);
        // 数据库查询
        page = plantFamilyMapper.selectPage(page, queryWrapper);
        // 结果封装
        long total = page.getTotal();
        List<PlantFamily> records = page.getRecords();
//        List<FamilyAdminVo> familyAdminVoList = new ArrayList<>();


        R ok = R.ok("查询成功",records,total);
        log.info("PlantFamilyServiceImpl.fuzzy业务结束，结果为:{}",ok);
        return ok;
    }

    /**
     * 查询科属id的所有子集id集合
     * 1.查询familyId相等的集合
     * 2.从集合中找出parentId==0的id集合，!=0存入结果Set集合中，Set集合去重
     * 3.再次查询数据库查询parentId等于该familyId的集合
     * 4.将新集合的id存入Set集合中
     * 5.将Set集合转成List后返回
     *
     * @param familyIdsParam 科属id集合
     * @return 科属id集合
     */
    @Override
    public List<Long> list(FamilyIdsParam familyIdsParam) {
        // 第一次查询，查询familyId相等的集合
        List<PlantFamily> plantFamilies = plantFamilyMapper.selectBatchIds(familyIdsParam.getIds());
        // 第二次查询条件封装
        List<Long> list = new ArrayList<>();
        Set<Long> set = new HashSet<>();
        for (PlantFamily plantFamily : plantFamilies) {
            Long id = plantFamily.getFamilyId();
            if(plantFamily.getParentId() == 0) {
                list.add(id);
            }
            set.add(id);
        }
        if(list != null && list.size() > 0) {
            QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper();
            queryWrapper.in("parent_id", list);
            // 第二次查询，查询数据库查询parentId等于该familyId的集合
            List<PlantFamily> plantFamilyList = plantFamilyMapper.selectList(queryWrapper);
            for (PlantFamily plantFamily : plantFamilyList) {
                set.add(plantFamily.getFamilyId());
            }
        }
        // 将set集合转回list集合
        List<Long> result = new ArrayList<>(set);
        log.info("PlantFamilyServiceImpl.list业务结束，结果为:{}",result);
        return result;
    }

    /**
     * 返回科属全称字符串接口
     * 1.数据库查询id对应名称
     * 2.查询父类id对应名称
     * 3.返回封装科属名称
     *
     * @param familyId 科属id
     * @return 科属名称
     */
    @Override
    public FamilyDto full(Long familyId) {
        FamilyDto familyDto = new FamilyDto();
        PlantFamily last = plantFamilyMapper.selectById(familyId);
        if(last == null) {
            log.info("PlantFamilyServiceImpl.full业务结束，结果为:{}","查询失败，不存在该名称");
            return null;
        }
        Long parentId = last.getParentId();
        if(parentId != 0) {
            PlantFamily first = plantFamilyMapper.selectById(parentId);
            familyDto.setFamilyName(first.getFamilyName());
            familyDto.setGenusId(first.getFamilyId());
        }
        familyDto.setGenusName(last.getFamilyName());
        log.info("PlantFamilyServiceImpl.full业务结束，结果为:{}",familyDto);
        return familyDto;
    }

    /**
     * 添加新属名
     * 1.正则校验是否符合规则
     * 2.查询同科下是否存在相同属名
     * 3.添加到数据库
     *
     * @param plantFamily
     * @return
     */
    @Override
    public R addGenus(PlantFamily plantFamily) {
        // 正则校验命名
        Pattern pattern = Pattern.compile(RegexConstant.PLANT_GENUS);
        Matcher matcher = pattern.matcher(plantFamily.getFamilyName());
        if(!matcher.matches()) {
            log.info("PlantFamilyServiceImpl.addFamily业务结束，结果为:{}","命名不符合规则");
            return R.fail("参数错误，添加失败");
        }
        // 数据库查询是否存在同科下同属名
        QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("family_name",plantFamily.getFamilyName());
        queryWrapper.eq("parent_id",plantFamily.getParentId());
        Long total = plantFamilyMapper.selectCount(queryWrapper);
        if(total > 0) {
            log.info("PlantFamilyServiceImpl.addFamily业务结束，结果为:{}","存在同名，添加失败");
            return R.fail("存在同名，添加失败");
        }
        // 添加到数据库
        plantFamilyMapper.insert(plantFamily);
        log.info("PlantFamilyServiceImpl.addFamily业务结束，结果为:{}","添加新属名成功");
        return R.ok("添加新属名成功");
    }

    /**
     * 返回科属树形目录
     * 1.数据库查询所有该种群下的科属
     * 2.处理查询到的集合，嵌套成树形目录
     * 2.1 第一次遍历找出所有科名
     * 2.2 第二次遍历找出科下所有属名
     * 3.返回封装结果
     *
     * @param categoryId 种群id
     * @return
     */
    @Override
    public R directory(Long categoryId) {
        // 数据库查询该种群下的所有科属
        QueryWrapper<PlantFamily> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id", categoryId);
        List<PlantFamily> plantFamilies = plantFamilyMapper.selectList(queryWrapper);
        // 嵌套成树形目录
        List<PlantFamilyVo> result = new ArrayList<>();
        Map<Long, PlantFamilyVo> map = new HashMap<>();
        // 第一次遍历，找出所有科名
        for (PlantFamily plantFamily : plantFamilies) {
            PlantFamilyVo plantFamilyVo = new PlantFamilyVo(plantFamily);
            // 如果父节点为空即为科名，直接存入结果集
            if (plantFamily.getParentId() == 0L) {
                result.add(plantFamilyVo);
            }
            map.put(plantFamilyVo.getFamilyId(), plantFamilyVo);
        }
        // 第二次遍历，找出科名下对应的属名
        for (PlantFamily plantFamily : plantFamilies) {
            // 覆盖父节点不为空即为属名，从map中找出父科存入其子集合中
            if (plantFamily.getParentId() != 0) {
                PlantFamilyVo plantFamilyVo = map.get(plantFamily.getParentId());
                plantFamilyVo.getChild().add(map.get(plantFamily.getFamilyId()));
            }
        }
        // 结果封装并返回
        R ok = R.ok(result);
        log.info("PlantFamilyServiceImpl.directory业务结束，结果为:{}", ok);
        return ok;
    }
}
